<script lang="ts" setup>
import { ref, computed, watch, onMounted, useAttrs } from 'vue';
import { ElInput, ElSelect, ElOption } from 'element-plus';

// 定义类型
type InputType =
  | 'text'
  | 'mixed'
  | 'number'
  | 'chinese'
  | 'english'
  | 'mobile'
  | 'email'
  | 'password'
  | 'money'
  | 'textarea';

interface OptionItem {
  label: string;
  value: string | number;
  prop?: string;
  disabled?: boolean;
}

interface Props {
  modelValue?: string | number | Record<string, any>;
  type?: InputType;
  maxlength?: number;
  minlength?: number;
  disabled?: boolean;
  options?: OptionItem[];
  selectWidth?: string;
  placeholder?: string;
  clearable?: boolean;
  showWordLimit?: boolean;
}

// 定义属性
const props = withDefaults(defineProps<Props>(), {
  type: 'text',
  maxlength: 20,
  minlength: 0,
  disabled: false,
  options: () => [],
  selectWidth: '100px',
  clearable: true,
  showWordLimit: false,
});

const inputOption = computed(() => {
  return props.options?.map((option) => ({
    label: option.label,
    value: option.value || option.prop || option.label,
    disabled: option.disabled,
  }));
});

// 定义事件
const emit = defineEmits<{
  (e: 'update:modelValue', value: any): void;
  (e: 'change', value: any): void;
  (e: 'clear'): void;
  (e: 'input', value: any): void;
  (e: 'blur', event: Event): void;
  (e: 'focus', event: Event): void;
  (e: 'mixed-option-select', value: any): void;
}>();

const attrs = useAttrs();
const selectValue = ref<OptionItem>();

// 计算属性
const computedPlaceholder = computed(() => {
  return props.disabled
    ? '该项只读'
    : props.placeholder || (attrs.placeholder as string) || '';
});

const computedMaxlength = computed(() => {
  // 根据输入类型设置不同的默认最大长度
  if (props.maxlength !== 20) return props.maxlength;

  switch (props.type) {
    case 'mobile':
      return 11;
    case 'email':
      return 50;
    case 'password':
      return 20;
    case 'money':
      return 15;
    default:
      return props.maxlength;
  }
});

// 监听选项变化
watch(
  () => inputOption.value,
  (newOptions) => {
    console.log(newOptions, 'newOptions');
    if (props.type === 'mixed' && newOptions.length > 0 && !selectValue.value) {
      // 默认选中第一个非禁用项
      const firstEnabledOption = newOptions.find((option) => !option.disabled);
      if (firstEnabledOption) {
        selectValue.value = firstEnabledOption;
        emit('mixed-option-select', selectValue.value.value);
      }
    }
  },
  { immediate: true }
);

// 监听selectValue变化
watch(selectValue, (newValue) => {
  console.log(newValue, 'newValue');
  if (props.type === 'mixed' && newValue) {
    // 当选择器值变化时，更新混合输入的值
    const currentValue = props.modelValue || {};
    if (!currentValue[newValue.value]) {
      const newModelValue = { ...currentValue, [newValue.value]: '' };
      emit('update:modelValue', newModelValue);
      emit('mixed-option-select', newValue.value);
    }
  }
});

// 处理输入事件
const handleInput = (value: string) => {
  const formattedValue = formatter(value);

  if (props.type === 'mixed' && selectValue.value) {
    const currentValue = (props.modelValue as Record<string, any>) || {};
    const newValue = {
      ...currentValue,
      [selectValue.value.value]: formattedValue,
    };
    emit('update:modelValue', newValue);
    emit('input', newValue);
  } else {
    emit('update:modelValue', formattedValue);
    emit('input', formattedValue);
  }
};

// 处理change事件
const handleChange = (value: any) => {
  emit('change', value);
};

// 处理clear事件
const handleClear = () => {
  emit('clear');
};

// 处理blur事件
const handleBlur = (event: Event) => {
  emit('blur', event);
};

// 处理focus事件
const handleFocus = (event: Event) => {
  emit('focus', event);
};

// 输入格式化方法
const formatter = (value: string): string => {
  if (typeof value !== 'string') return value;

  switch (props.type) {
    case 'number':
      return value.replace(/\D+/g, '');
    case 'chinese':
      return value.replace(/[^\u4e00-\u9fa5]/g, '');
    case 'english':
      return value.replace(/[^a-zA-Z\s]/g, '');
    case 'mobile':
      return value.replace(/\D+/g, '').slice(0, 11);
    case 'email':
      // 允许邮箱常用字符
      return value.replace(/[^a-zA-Z0-9@._-]/g, '');
    case 'password':
      // 密码允许的字符范围更广
      return value.replace(/\s/g, '');
    case 'money':
      // 金额格式化
      let cleaned = value.replace(/[^\d.]/g, '');
      // 处理多个点号的情况，只保留第一个
      const dotIndex = cleaned.indexOf('.');
      if (dotIndex > -1) {
        const beforeDot = cleaned.substring(0, dotIndex + 1);
        const afterDot = cleaned.substring(dotIndex + 1).replace(/\./g, '');
        cleaned = beforeDot + afterDot;
        // 限制小数点后两位
        if (afterDot.length > 2) {
          cleaned = beforeDot + afterDot.substring(0, 2);
        }
      }
      // 防止以小数点开头
      if (cleaned === '.') cleaned = '';
      return cleaned;
    default:
      return value;
  }
};

// 获取当前输入值（用于mixed类型）
const getCurrentValue = () => {
  if (props.type !== 'mixed' || !selectValue.value) return '';

  const modelValue = props.modelValue || {};
  return modelValue[selectValue.value.value] !== undefined
    ? modelValue[selectValue.value.value]
    : '';
};

// defineExpose({
//   getCurrentValue,
// })
</script>

<template>
  <div class="xt-input">
    <el-input
      v-if="type === 'mixed'"
      :model-value="getCurrentValue()"
      :disabled="disabled"
      :maxlength="computedMaxlength"
      :minlength="minlength"
      :placeholder="computedPlaceholder"
      :clearable="clearable"
      :show-word-limit="showWordLimit"
      @blur="handleBlur"
      @focus="handleFocus"
      @change="handleChange"
      @clear="handleClear"
      @input="handleInput">
      <template #prepend>
        <el-select
          v-model="selectValue"
          :disabled="disabled"
          :style="{ width: selectWidth }">
          <el-option
            v-for="option in inputOption"
            :key="option.value"
            :label="option.label"
            :disabled="option.disabled"
            :value="option" />
        </el-select>
      </template>
    </el-input>

    <el-input
      v-else-if="type === 'textarea'"
      v-bind="$attrs"
      type="textarea"
      :model-value="modelValue"
      :disabled="disabled"
      :maxlength="computedMaxlength"
      :minlength="minlength"
      :placeholder="computedPlaceholder"
      :clearable="clearable"
      :show-word-limit="showWordLimit"
      @blur="handleBlur"
      @focus="handleFocus"
      @change="handleChange"
      @clear="handleClear"
      @input="handleInput" />

    <el-input
      v-else
      :model-value="modelValue"
      v-bind="$attrs"
      :type="type === 'password' ? 'password' : 'text'"
      :disabled="disabled"
      :maxlength="computedMaxlength"
      :minlength="minlength"
      :placeholder="computedPlaceholder"
      :clearable="clearable"
      :show-word-limit="showWordLimit"
      @blur="handleBlur"
      @focus="handleFocus"
      @change="handleChange"
      @clear="handleClear"
      @input="handleInput" />
  </div>
</template>

<style scoped>
.xt-input {
  width: 100%;
}

:deep(.el-input-group__prepend) {
  padding: 0;
}

:deep(.el-select) {
  width: 100%;
}

:deep(.el-select .el-input) {
  width: 100%;
}
</style>
